package com.mine.modules.vm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.mine.common.config.exception.MineBootException;
import com.mine.common.domain.vo.Result;
import com.mine.common.utils.oConvertUtils;
import com.mine.modules.sys.entity.SysDictItem;
import com.mine.modules.vm.common.constant.BizConstant;
import com.mine.modules.vm.common.utils.InvokeUtils;
import com.mine.modules.vm.domain.dto.AddElementDto;
import com.mine.modules.vm.domain.query.ElementPageQuery;
import com.mine.modules.vm.entity.*;
import com.mine.modules.vm.mapper.VmLayerElementMapper;
import com.mine.modules.vm.service.IVmLayerElementService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 场景菜单 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-10-18
 */
@Service
public class VmLayerElementServiceImpl extends ServiceImpl<VmLayerElementMapper, VmLayerElement> implements IVmLayerElementService {

    @Override
    public Result<?> queryPageList(ElementPageQuery pageQuery) {
        LambdaQueryWrapper<VmLayerElement> queryWrapper = new LambdaQueryWrapper<>(VmLayerElement.class);
        if (StringUtils.isNotBlank(pageQuery.getKeywords())) {
            queryWrapper.and(wrapper -> wrapper
                    .like(VmLayerElement::getElementCode, pageQuery.getKeywords())
                    .or()
                    .like(VmLayerElement::getElementName, pageQuery.getKeywords())
            );
        }
        queryWrapper.eq(VmLayerElement::getLayerId, pageQuery.getLayerId());
        queryWrapper.eq(VmLayerElement::getElementType, pageQuery.getElementType());
        Page<VmLayerElement> page = new Page<>(pageQuery.getPageNo(), pageQuery.getPageSize());
        return Result.ok(this.page(page, queryWrapper));
    }

    @Override
    public Result<?> addOrEdit(AddElementDto addElementDto) {
        if (addElementDto == null) {
            return Result.error("参数必填！");
        }
        if (StringUtils.isEmpty(addElementDto.getId())) {
            //新增
            VmLayerElement vmLayerElement = BeanUtil.toBean(addElementDto, VmLayerElement.class);
            if (StringUtils.isBlank(addElementDto.getElementType())) {
                vmLayerElement.setElementType(BizConstant.SCENE_ELEMENT_TYPE_ELEMENT);
            }
            if (this.save(vmLayerElement)) {
                return Result.OK("添加成功！");
            } else {
                return Result.error("添加失败！");
            }
        } else {
            VmLayerElement vmLayerElement = this.getById(addElementDto.getId());
            if (vmLayerElement == null) {
                return Result.error("数据不存在，请刷新重试！");
            }
            if (StringUtils.isBlank(addElementDto.getElementType())) {
                vmLayerElement.setElementType(BizConstant.SCENE_ELEMENT_TYPE_ELEMENT);
            }
            String sceneLayerId = vmLayerElement.getSceneLayerId();
            vmLayerElement = BeanUtil.toBean(addElementDto, VmLayerElement.class);
            vmLayerElement.setSceneLayerId(sceneLayerId);
            if (this.updateById(vmLayerElement)) {
                return Result.OK("修改成功！");
            } else {
                return Result.error("修改失败！");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> delete(String id) {
        try {
            if (this.removeById(id)) {
                //删除传感器绑定
                Db.lambdaUpdate(VmSensorElement.class).eq(VmSensorElement::getElementId, id).remove();
            }
            return Result.OK("删除成功!");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> deleteBatch(String ids) {
        try {
            String[] arr = ids.split(",");
            for (String id : arr) {
                if (oConvertUtils.isNotEmpty(id)) {
                    try {
                        this.delete(id);
                    } catch (MineBootException e) {
                        if (e.getMessage() != null && e.getMessage().contains("未找到数据")) {
                            log.warn(e.getMessage());
                        } else {
                            throw e;
                        }
                    }
                }
            }
            return Result.OK("删除成功!");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error("删除失败!");
        }
    }

    @Override
    public Result<?> bindSceneLayerOfElement(String sId, String sceneLayerId) {
        if (StringUtils.isBlank(sId) || StringUtils.isBlank(sceneLayerId)) {
            return Result.error("参数不完整！");
        }
        VmLayerElement vmLayerElement = this.getById(sId);
        if (vmLayerElement == null) {
            return Result.error("图元不存在，请刷新重试！");
        }
        vmLayerElement.setSceneLayerId(sceneLayerId);
        if (this.updateById(vmLayerElement)) {
            return Result.ok("操作成功！");
        } else {
            return Result.error("操作失败！");
        }
    }

    @Override
    public Result<?> cleanSceneLayerOfElement(String sId) {
        if (StringUtils.isBlank(sId)) {
            return Result.error("参数不完整！");
        }
        VmLayerElement vmLayerElement = this.getById(sId);
        if (vmLayerElement == null) {
            return Result.error("图元不存在，请刷新重试！");
        }
        vmLayerElement.setSceneLayerId(null);
        if (this.updateById(vmLayerElement)) {
            return Result.ok("操作成功！");
        } else {
            return Result.error("操作失败！");
        }
    }

    @Override
    public List<String> getElementIdsByLayerIdOrType(String layerId, String elementType) {
        return lambdaQuery()
                .eq(StringUtils.isNotBlank(layerId), VmLayerElement::getLayerId, layerId)
                .eq(StringUtils.isNotBlank(elementType), VmLayerElement::getElementType, elementType)
                .list()
                .stream()
                .map(VmLayerElement::getElementId)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());
    }

    @Override
    public Result<?> getDetailsId(String id) {
        VmLayerElement vmLayerElement = getById(id);
        if (vmLayerElement == null) {
            return Result.error("数据不存在，请刷新重试！");
        }
        SysDictItem sysDictItem = Db.lambdaQuery(SysDictItem.class).eq(SysDictItem::getItemValue, vmLayerElement.getElementType()).one();
        if (sysDictItem == null) {
            return Result.error("数据不存在，请刷新重试！");
        }
        return Result.ok(
                InvokeUtils.invokeByMethod(sysDictItem.getExtendService(), BizConstant.COMMON_ELEMENT_ROW_BY_ID_METHOD, String.valueOf(vmLayerElement.getElementId()))
        );
    }

    @Override
    public Result<?> getSensorBySceneLayerId(String sceneLayerId) {
        if (StringUtils.isEmpty(sceneLayerId)) {
            return Result.error("参数必填！");
        }
        List<String> ids = this.lambdaQuery()
                .eq(VmLayerElement::getSceneLayerId, sceneLayerId)
                .list()
                .stream()
                .map(VmLayerElement::getElementId)
                .collect(Collectors.toList());
        if (ids.isEmpty()) {
            return Result.error("未绑定数据！");
        }
        List<String> sensorIds = Db.lambdaQuery(VmSensorElement.class)
                .in(VmSensorElement::getElementId, ids)
                .list()
                .stream()
                .map(VmSensorElement::getSensorId)
                .collect(Collectors.toList());
        if (sensorIds.isEmpty()) {
            return Result.ok(Collections.EMPTY_LIST);
        }
        return Result.ok(Db.lambdaQuery(VmScene.class).in(VmScene::getId, sensorIds).list());
    }

    @Override
    public Result<?> getDetailsBySceneLayerId(String sceneLayerId) {
        VmLayerElement vmLayerElement = this.lambdaQuery()
                .eq(VmLayerElement::getSceneLayerId, sceneLayerId)
                .last(" limit 1 ")
                .one();
        if (vmLayerElement == null) {
            return Result.error("图元不存在，请刷新重试！");
        }
        return Result.ok(vmLayerElement);
    }

    @Override
    public void addElement(AddElementDto addElementDto) {
        if (addElementDto == null) {
            return;
        }
        //新增
        VmLayerElement vmLayerElement = BeanUtil.toBean(addElementDto, VmLayerElement.class);
        if (StringUtils.isBlank(addElementDto.getElementType())) {
            vmLayerElement.setElementType(BizConstant.SCENE_ELEMENT_TYPE_ELEMENT);
        }
        this.save(vmLayerElement);
    }

    @Override
    public void copyElementActionByLayerId(String sourceLayerId, String targetLayerId) {
        List<VmLayerElement> elements = this.lambdaQuery().eq(VmLayerElement::getLayerId, sourceLayerId).list();
        List<VmLayerElement> newElements = new ArrayList<>();
        for (VmLayerElement element : elements) {
            element.setId(UUID.randomUUID().toString());
            element.setLayerId(targetLayerId);
            newElements.add(element);
        }
        if(!newElements.isEmpty()){
            this.saveBatch(newElements);
        }
    }

}
